import sys
import os
import subprocess
import tkinter as tk
import time
import random
import threading
from random import randint
from win32api import GetMonitorInfo, MonitorFromPoint
from pynput import mouse, keyboard

def resource_path(relative_path):
    """获取资源文件绝对路径，兼容开发环境和PyInstaller打包后的环境"""
    if hasattr(sys, '_MEIPASS'):
        return os.path.join(sys._MEIPASS, relative_path)
    return os.path.join(os.path.abspath("."), relative_path)

monitor_info = GetMonitorInfo(MonitorFromPoint((0, 0)))
work_area = monitor_info.get('Work')
screen_width = work_area[2]
work_height = work_area[3]

# 事件编号
idle_num = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
sleep_num = [19, 20, 21, 22, 23, 24, 25]
walk_left = [13, 14, 15]
walk_right = [16, 17, 18]

class Ket:
    def __init__(self):
        self.window = tk.Tk()
        self.reading_start_time = None  # 初始化开始时间

        self.idle = [tk.PhotoImage(file=resource_path(f'assets/idle{i}.png')) for i in range(1, 5)]
        self.idle_to_sleeping = [tk.PhotoImage(file=resource_path(f'assets/sleeping{i}.png')) for i in range(1, 7)]
        self.sleeping = [tk.PhotoImage(file=resource_path(f'assets/zzz{i}.png')) for i in range(1, 5)]
        self.sleeping_to_idle = list(reversed(self.idle_to_sleeping))

        self.walking_left = [tk.PhotoImage(file=resource_path(f'assets/walkingleft{i}.png')) for i in range(1, 5)]
        self.walking_right = [tk.PhotoImage(file=resource_path(f'assets/walkingright{i}.png')) for i in range(1, 5)]

        self.reading = [tk.PhotoImage(file=resource_path(f'assets/books/read_book_{i}.png')) for i in range(1, 5)]

        self.x = int(screen_width * 0.8)
        self.y = work_height - 64

        self.i_frame = 0
        self.state = 1
        self.event_number = randint(1, 3)

        self.frame = self.idle[0]

        self.window.config(highlightbackground='black')
        self.label = tk.Label(self.window, bd=0, bg='black')
        self.window.overrideredirect(True)
        self.window.attributes('-topmost', True)
        self.window.wm_attributes('-transparentcolor', 'black')
        self.label.pack()

        # 添加右键菜单
        self.menu = tk.Menu(self.window, tearoff=0)
        self.menu.add_command(label="重启", command=self.restart)   # 索引0
        self.menu.add_command(label="看书", command=self.toggle_reading)  # 索引1
        self.menu.add_command(label="退出", command=self.window.destroy)  # 索引2
        self.label.bind("<Button-3>", self.show_menu)

        self.active_time = 0
        self.last_input_time = time.time()
        self.reading_started = False

        self.seconds = 40 * 60  # 40分钟，单位为秒。你可以改成任意你想要的间隔

        # 启动监听线程
        threading.Thread(target=self.listen_input, daemon=True).start()
        threading.Thread(target=self.check_active, daemon=True).start()

        # 启动动画更新
        self.window.after(1, self.update, self.i_frame, self.state, self.event_number, self.x)
        self.window.mainloop()

    def event(self, i_frame, state, event_number, x):
        if self.state == 6:
            return  # 看书状态不打断

        if self.event_number in idle_num:
            self.state = 0
            self.window.after(400, self.update, self.i_frame, self.state, self.event_number, self.x)
        elif self.event_number == 12:
            self.state = 1
            self.window.after(100, self.update, self.i_frame, self.state, self.event_number, self.x)
        elif self.event_number in walk_left:
            self.state = 4
            self.window.after(100, self.update, self.i_frame, self.state, self.event_number, self.x)
        elif self.event_number in walk_right:
            self.state = 5
            self.window.after(100, self.update, self.i_frame, self.state, self.event_number, self.x)
        elif self.event_number in sleep_num:
            self.state = 2
            self.window.after(400, self.update, self.i_frame, self.state, self.event_number, self.x)
        elif self.event_number == 26:
            self.state = 3
            self.window.after(100, self.update, self.i_frame, self.state, self.event_number, self.x)

    def animate(self, i_frame, array, event_number, a, b):
        if self.i_frame < len(array) - 1:
            self.i_frame += 1
        else:
            self.i_frame = 0
            self.event_number = randint(a, b)
        return self.i_frame, self.event_number

    def update(self, i_frame, state, event_number, x):
        if self.state == 0:
            self.frame = self.idle[self.i_frame]
            self.i_frame, self.event_number = self.animate(self.i_frame, self.idle, self.event_number, 1, 18)
        elif self.state == 1:
            self.frame = self.idle_to_sleeping[self.i_frame]
            self.i_frame, self.event_number = self.animate(self.i_frame, self.idle_to_sleeping, self.event_number, 19, 19)
        elif self.state == 2:
            self.frame = self.sleeping[self.i_frame]
            self.i_frame, self.event_number = self.animate(self.i_frame, self.sleeping, self.event_number, 19, 26)
        elif self.state == 3:
            self.frame = self.sleeping_to_idle[self.i_frame]
            self.i_frame, self.event_number = self.animate(self.i_frame, self.sleeping_to_idle, self.event_number, 1, 1)
        elif self.state == 4:
            if self.x > 0:
                self.frame = self.walking_left[self.i_frame]
                self.i_frame, self.event_number = self.animate(self.i_frame, self.walking_left, self.event_number, 1, 18)
                self.x -= 3
            else:
                self.state = 5
                self.event_number = random.choice(walk_right + idle_num)
                self.x += 3
        elif self.state == 5:
            if self.x < (screen_width - 72):
                self.frame = self.walking_right[self.i_frame]
                self.i_frame, self.event_number = self.animate(self.i_frame, self.walking_right, self.event_number, 1, 18)
                self.x += 3
            else:
                self.state = 4
                self.event_number = random.choice(walk_left + idle_num)
        elif self.state == 6:
            self.frame = self.reading[self.i_frame]
            self.i_frame = (self.i_frame + 1) % len(self.reading)

        self.window.geometry(f'72x64+{self.x}+{self.y}')
        self.label.configure(image=self.frame)

        # 更新动画切换速度
        if self.state in [0, 2]:  # idle, sleeping
            self.window.after(400, self.event, self.i_frame, self.state, self.event_number, self.x)
        elif self.state == 6:
            self.window.after(400, self.update, self.i_frame, self.state, self.event_number, self.x)
        elif self.state in [1, 3, 4, 5]:  # 其它动画
            self.window.after(25, self.event, self.i_frame, self.state, self.event_number, self.x)
        else:
            self.window.after(1, self.event, self.i_frame, self.state, self.event_number, self.x)
        
    def start_reading(self):
        self.state = 6
        self.i_frame = 0
        self.event_number = 88  # dummy
        self.reading_start_time = time.time()  # ✅ 记录开始阅读的时间
        self.window.after(100, self.update, self.i_frame, self.state, self.event_number, self.x)

    def toggle_reading(self):
        if self.state == 6:
            # 停止看书，进入睡觉状态
            self.state = 2
            self.i_frame = 0
            self.event_number = 19
        else:
            # 开始看书
            self.start_reading()

    def show_menu(self, event):
        if self.state == 6:
            self.menu.entryconfig(1, label="不看啦")
        else:
            self.menu.entryconfig(1, label="看书")
        self.menu.tk_popup(event.x_root, event.y_root)


    def restart(self):
        script_path = os.path.abspath(sys.argv[0])
        args = [sys.executable, script_path] + sys.argv[1:]
        subprocess.Popen(args)
        sys.exit()

    def listen_input(self):
        def on_move(x, y):
            self.last_input_time = time.time()

        def on_click(x, y, button, pressed):
            self.last_input_time = time.time()

        def on_scroll(x, y, dx, dy):
            self.last_input_time = time.time()

        with mouse.Listener(on_move=on_move, on_click=on_click, on_scroll=on_scroll) as listener:
            listener.join()


    def load_reminders(self, filepath: str) -> list:
        with open(filepath, 'r', encoding='utf-8') as f:
            lines = [line.strip() for line in f if line.strip()]
        return lines

    def get_cat_reminder(self, minutes: int, reminders: list) -> str:
        template = random.choice(reminders)
        try:
            return template.format(minutes)
        except Exception:
            return template

    def show_message(self):
        # 加载提醒文本
        reminders = self.load_reminders("message/read_relax.txt")
        seconds = int(self.seconds / 60)  # 实际可根据需要动态设置
        message = self.get_cat_reminder(seconds, reminders)

        bubble = tk.Toplevel(self.window)
        bubble.overrideredirect(True)
        bubble.attributes('-topmost', True)
        bubble.attributes('-alpha', 0.9)
        bubble.configure(bg="#f0f0f0", padx=10, pady=5)

        label = tk.Label(bubble, text=message, font=("微软雅黑", 10), bg="#f0f0f0", fg="#333", wraplength=200, justify='left')
        label.pack(pady=(10, 5))

        # 设置气泡位置
        x = self.x - 60
        y = self.y - 80
        bubble.geometry(f"+{x}+{y}")
        bubble.after(10000, bubble.destroy)


    def check_active(self):
        active_seconds = 0
        while True:
            time.sleep(1)
            # 1.5秒内有操作则累计活跃时间，否则清零
            if time.time() - self.last_input_time < 1.5:
                active_seconds += 1
            else:
                active_seconds = 0

            # 连续活跃超过60秒，进入看书
            if active_seconds >= 60 and self.state != 6:
                self.start_reading()

            # 超过5分钟未操作，退出看书
            if self.state == 6 and time.time() - self.last_input_time > 300:
                self.state = 2  # 进入睡觉或其它状态
                self.i_frame = 0
                self.event_number = 19

            # 监测时长并每隔 seconds 触发提醒
            if self.state == 6 and self.reading_start_time:
                if time.time() - self.reading_start_time >= self.seconds:
                    self.show_message()
                    self.reading_start_time = time.time()  # 重置为当前时间，实现循环提醒


ket = Ket()
